package com.dbsop.request;

import com.dbsop.common.util.FieldUtils;
import com.dbsop.config.EsClientConfig;
import com.dbsop.domain.info.EsFiledInfo;
import com.dbsop.exception.EsRunException;
import com.dbsop.mapper.ESBaseMapper;
import com.dbsop.mapper.IndexMappingInfo;
import com.dbsop.operation.field.FieldOperation;
import com.dbsop.operation.index.IndexOperation;
import com.dbsop.operation.index.IndexParams;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@Slf4j
public abstract class ClientOpt {

    protected List<ESBaseMapper> esBaseMappers;

    protected EsClientConfig esClientConfig;

    protected ClientRequest clientRequest;

    protected FieldOperation fieldOperation;

    protected IndexOperation indexOperation;

    public ClientOpt(EsClientConfig esClientConfig,List<ESBaseMapper> esBaseMappers) {
        this.esBaseMappers = esBaseMappers;
        this.esClientConfig = esClientConfig;

    }

    public void init(){
        initClient();
        initOperation();
//        poxyOpt();
        initRepository();

    }

    public ClientRequest getClientRequest() {
        return clientRequest;
    }

    public FieldOperation getFieldOperation() {
        return fieldOperation;
    }

    public IndexOperation getIndexOperation() {
        return indexOperation;
    }

    /**
     * 初始化客户端
     */
    protected abstract void initClient();

    /**
     * 初始化一些操作;
     */
    protected abstract void initOperation();

    protected void poxyOpt(){
        ClientRequest clientRequestStore = clientRequest;
        InvocationHandler invocationHandler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Long start = System.currentTimeMillis();
                Object invoke = method.invoke(clientRequestStore, args);
                Long end =System.currentTimeMillis();
                log.info("调用总耗时"+method.getName()+"方法耗时:" +(end-start) +"毫秒");
                return invoke;
            }
        };
         this.clientRequest = (ClientRequest) Proxy.newProxyInstance(invocationHandler.getClass().getClassLoader(),
                new Class[]{ClientRequest.class},invocationHandler);
    }

    /**
     * 初始化索引映射
     */
    private   void initRepository(){
        // 是否自动创建索引
        if (!esClientConfig.getProperties().getIsAutoBuildTable())return;
        List<ESBaseMapper> esBaseMappers = new ArrayList<ESBaseMapper>();

        for (ESBaseMapper esBaseMapper: this.esBaseMappers) {
            esBaseMapper.init();
            IndexMappingInfo infoMapping = (IndexMappingInfo) FieldUtils.getFieldValue(esBaseMapper, "infoMapping");
            if(infoMapping.isExt()){
                esBaseMappers.add(esBaseMapper);
                continue;
            }
            // 自动创建与否
            if (infoMapping.isAutoCreate()){
                Set<String> indices = infoMapping.getIndices();
                indices.add(infoMapping.getIndexName());
                for (String indexName : indices) {
                    List<EsFiledInfo> esFiledInfos = infoMapping.getEsFiledInfos();
                    indexOperation.checkCreateIndex( new IndexParams(infoMapping.getIndexName(),infoMapping.getAlias(),infoMapping.getShared(),
                            infoMapping.getReplicas(),infoMapping.getMaxResult()));
                    Boolean isSame = fieldOperation.checkIndexFields(indexName, esFiledInfos);
                    if (!isSame)fieldOperation.createIndexFiled(indexName,esFiledInfos);
                    log.info("索引:"+indexName+"  加载完成 ");
                    infoMapping.addSucceedIndex(indexName);
                }
            }
        }
        for (ESBaseMapper esBaseMapper : esBaseMappers) {
            IndexMappingInfo infoMapping = (IndexMappingInfo) FieldUtils.getFieldValue(esBaseMapper, "infoMapping");
            // 继承列表
            if (infoMapping.isExt()){
                Set<String> indices = infoMapping.getIndices();
                indices.add(infoMapping.getIndexName());
                for (String indexName : indices) {
                    if (!indexOperation.existsIndex(infoMapping.getIndexName()))throw new EsRunException("ES index :" + indexName + "not found !!!");
                    List<EsFiledInfo> esFiledInfos = infoMapping.getEsFiledInfos();
                    fieldOperation.checkContain(indexName,esFiledInfos);
                    log.info("索引:"+indexName+" 扩展分表 " + infoMapping.getEntity().getName() +" 加载完成");
                    infoMapping.addSucceedIndex(indexName);
                }
                continue;
            }
        }
    }


}
